import type { PolymorphicProps } from '@kobalte/core/polymorphic';
import type {
  SelectContentProps,
  SelectItemProps,
  SelectTriggerProps,
} from '@kobalte/core/select';
import type { JSX, ParentProps, ValidComponent } from 'solid-js';
import { Select as SelectPrimitive } from '@kobalte/core/select';
import { splitProps } from 'solid-js';
import { cn } from '@/modules/shared/style/cn';

export const Select = SelectPrimitive;
export const SelectValue = SelectPrimitive.Value;
export const SelectDescription = SelectPrimitive.Description;
export const SelectErrorMessage = SelectPrimitive.ErrorMessage;
export const SelectItemDescription = SelectPrimitive.ItemDescription;
export const SelectHiddenSelect = SelectPrimitive.HiddenSelect;
export const SelectSection = SelectPrimitive.Section;

type selectTriggerProps<T extends ValidComponent = 'button'> = ParentProps<SelectTriggerProps<T> & { class?: string; caretIcon?: JSX.Element }>;

export function SelectTrigger<T extends ValidComponent = 'button'>(props: PolymorphicProps<T, selectTriggerProps<T>>) {
  const [local, rest] = splitProps(props as selectTriggerProps, [
    'class',
    'children',
    'caretIcon',
  ]);

  return (
    <SelectPrimitive.Trigger
      class={cn(
        'flex h-9 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus-visible:(ring-1.5 ring-ring) disabled:(cursor-not-allowed opacity-50) transition-shadow',
        local.class,
      )}
      {...rest}
    >
      {local.children}
      {local.caretIcon !== undefined
        ? local.caretIcon
        : (
            <SelectPrimitive.Icon
              as="svg"
              xmlns="http://www.w3.org/2000/svg"
              width="1em"
              height="1em"
              viewBox="0 0 24 24"
              class="size-4 opacity-50 flex items-center justify-center"
            >
              <path
                fill="none"
                stroke="currentColor"
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="2"
                d="m8 9l4-4l4 4m0 6l-4 4l-4-4"
              />
            </SelectPrimitive.Icon>
          )}
    </SelectPrimitive.Trigger>
  );
}

type selectContentProps<T extends ValidComponent = 'div'>
  = SelectContentProps<T> & {
    class?: string;
  };

export function SelectContent<T extends ValidComponent = 'div'>(props: PolymorphicProps<T, selectContentProps<T>>) {
  const [local, rest] = splitProps(props as selectContentProps, ['class']);

  return (
    <SelectPrimitive.Portal>
      <SelectPrimitive.Content
        class={cn(
          'relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[expanded]:(animate-in fade-in-0 zoom-in-95) data-[closed]:(animate-out fade-out-0 zoom-out-95)',
          local.class,
        )}
        {...rest}
      >
        <SelectPrimitive.Listbox class="p-1 focus-visible:outline-none" />
      </SelectPrimitive.Content>
    </SelectPrimitive.Portal>
  );
}

type selectItemProps<T extends ValidComponent = 'li'> = ParentProps<SelectItemProps<T> & { class?: string }>;

export function SelectItem<T extends ValidComponent = 'li'>(props: PolymorphicProps<T, selectItemProps<T>>) {
  const [local, rest] = splitProps(props as selectItemProps, [
    'class',
    'children',
  ]);

  return (
    <SelectPrimitive.Item
      class={cn(
        'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:(bg-accent text-accent-foreground) data-[disabled]:(pointer-events-none opacity-50)',
        local.class,
      )}
      {...rest}
    >
      <SelectPrimitive.ItemIndicator class="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
        <svg
          xmlns="http://www.w3.org/2000/svg"
          class="h-4 w-4"
          viewBox="0 0 24 24"
        >
          <path
            fill="none"
            stroke="currentColor"
            stroke-linecap="round"
            stroke-linejoin="round"
            stroke-width="2"
            d="m5 12l5 5L20 7"
          />
          <title>Checked</title>
        </svg>
      </SelectPrimitive.ItemIndicator>
      <SelectPrimitive.ItemLabel>{local.children}</SelectPrimitive.ItemLabel>
    </SelectPrimitive.Item>
  );
}
